// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

#region

using Furion.DataEncryption;
using Microsoft.AspNetCore.Http;
using Neto.Application.Api;
using Neto.Core.CommonDto.Api;
using Neto.Db.SqlSugar;
using Neto.Db.SqlSugar.Paged;
using Neto.Encry;

#endregion

namespace Neto.Application.ApiAdmin.User;

/// <summary>
///     用户服务
/// </summary>
/// <param name="db"></param>
[Authorize]
[ApiDescriptionSettings("Api", Name = "User")]
[ApiArea]
[PgApiController("用户服务", MenuPCode = "Sys_Manage")]
[PgApiMenu("用户管理", "manage_user", MenuPCode = "Sys_Manage", Icon = "ic:round-manage-accounts", Sort = 1)]
public class ApiUserService(ISqlSugarClient db)
    : IDynamicApiController
{
    /// <summary>
    ///     获取当前登录信息
    /// </summary>
    /// <returns></returns>
    [PgApiAction("获取当前登录信息", Action = "GetLoginInfo", Sort = 1)]
    public async Task<ApiUserOut> GetLoginInfo()
    {
        //获取请求头
        var head = App.HttpContext;
        var token = JWTEncryption.GetJwtBearerToken((DefaultHttpContext)head);
        var (isValid, tokenData, validationResult) = JWTEncryption.Validate(token);
        if (isValid && validationResult.Claims.ContainsKey("UserId"))
        {
            var userid = Convert.ToInt64(validationResult.Claims["UserId"]);

            var user = await db.Queryable<SysUser>().Includes(o => o.Roles)
                .FirstAsync(o => o.Id == userid);

            return user.Adapt<ApiUserOut>();
        }

        return null;
    }

    /// <summary>
    ///     获取用户列表
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [OperationId(nameof(GetPagedList))]
    [PgApiAction("获取用户列表", Action = "GetPagedList", Sort = 2)]
    public async Task<PagedList<ApiUserOut>> GetPagedList(ApiUserQuery query)
    {
        var queryable = db.Queryable<SysUser>();

        if (query.UserType.HasValue) queryable = queryable.Where(su => su.UserType == query.UserType.Value);
        //if (!string.IsNullOrWhiteSpace(query.Account))
        //    queryable = queryable.Where(su => su.Account.ToLower().Contains(query.Account));
        //if (!string.IsNullOrWhiteSpace(query.Nick))
        //    queryable = queryable.Where(su => su.Nick.ToLower().Contains(query.Nick));
        //if (!string.IsNullOrWhiteSpace(query.Phone))
        //    queryable = queryable.Where(su => su.Phone.ToLower().Contains(query.Phone));

        //if (!string.IsNullOrWhiteSpace(query.Account))
        //    queryable = queryable.Where(su => su.Account.ToLower().Contains(query.Account));

        if (query.IsEnable.HasValue) queryable = queryable.Where(su => su.IsEnable == query.IsEnable);

        if (query.StartTime.HasValue) queryable = queryable.Where(su => su.CreationTime >= query.StartTime.Value);
        if (query.EndTime.HasValue) queryable = queryable.Where(su => su.CreationTime <= query.EndTime.Value);

        if (!string.IsNullOrWhiteSpace(query.KeyWords))
        {
            var kw = query.KeyWords?.Trim()?.ToLower() ?? "";
            if (kw.IsValidLong() || kw.IsValidInt32())
            {
                var tempId = Convert.ToInt64(kw);
                queryable = queryable.Where(su =>
                    su.Account.Contains(query.KeyWords) ||
                    su.Nick.Contains(query.KeyWords) ||
                    su.Id == tempId
                );
            }
            else
                queryable = queryable.Where(su =>
                    su.Account.Contains(query.KeyWords) ||
                    su.Nick.Contains(query.KeyWords)
                );
        }


        var list = await queryable
            .OrderBy(su => su.Id)
            .Select(su => new ApiUserOut
            {
                Id = su.Id.SelectAll(),
                RoleIds = SqlFunc.Subqueryable<SysUserRole>()
                    .Where(sur => sur.UserId == su.Id)
                    .ToList(sur => sur.RoleId),
                RoleName = SqlFunc.Subqueryable<SysUserRole>()
                    .InnerJoin<SysRole>((sur, sr) => sur.RoleId == sr.Id)
                    .Where((sur, sr) => sur.UserId == su.Id)
                    .SelectStringJoin((sur, sr) => SqlFunc.MappingColumn<string>($"distinct {sr.Name}"), ",")
                //自动映射
            }, true)
            .Mapper(it =>
            {
                //it.RoleIds = it.RoleIdStr.Split(',').Select(i => Convert.ToInt64(i)).ToList();
            })
            .ToPagedListAsync(query.PageIndex, query.PageSize);


        return list;
    }


    /// <summary>
    ///     添加或者修改
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [OperationId(nameof(InsertOrUpdate))]
    [PgApiAction("添加或者修改", Action = "InsertOrUpdate", Sort = 3)]
    public async Task<long> InsertOrUpdate(ApiUserInput input)
    {
        //var roleids = input.RoleIds.ToLongList();
        if (input.Id > 0)
        {
            #region 修改

            //判断账号是否已存在，防止重复添加相同账号
            if (db.Queryable<SysUser>().Any(o => o.Id != input.Id && o.Account == input.Account))
                throw Oops.Bah($"账号:{input.Account} 已存在");

            var dbentity = await db.Queryable<SysUser>().Includes(o => o.Roles).FirstAsync(o => o.Id == input.Id);
            if (!string.IsNullOrWhiteSpace(input.Pwd)) dbentity.Pwd = input.Pwd.ToPBKDF2Hash();
            input.Adapt(dbentity);


            //删除移除了的 用户角色
            if (dbentity.Roles != null && dbentity.Roles.Any())
            {
                var delroleids = dbentity.Roles.Where(o => input.RoleIds.All(a => a != o.Id)).Select(a => a.Id)
                    .ToList();
                await db.Deleteable<SysUserRole>().Where(o => o.UserId == input.Id && delroleids.Contains(o.RoleId))
                    .ExecuteCommandAsync();
            }

            //新增添加的用户角色
            var adds = new List<SysUserRole>();
            foreach (var roleid in input.RoleIds)
            {
                if (dbentity.Roles != null && dbentity.Roles.Any(o => o.Id == roleid)) continue;
                adds.Add(new SysUserRole { RoleId = roleid, UserId = input.Id.Value });
            }

            if (adds.Count > 0) await db.InsertAsync(adds);

            await db.Updateable(dbentity).ExecuteCommandAsync();

            #endregion 修改

            return dbentity.Id;
        }
        else
        {
            #region 新增

            //判断账号是否已存在，防止重复添加相同账号
            if (db.Queryable<SysUser>().Any(o => o.Account == input.Account))
                throw Oops.Bah($"账号:{input.Account} 已存在");
            var addentity = input.Adapt<SysUser>();
            //addentity.Roles = new List<SysUserRole>();

            addentity.UserType = UserType.管理员;
            addentity.Pwd = input.Pwd?.ToPBKDF2Hash();
            var userid = await db.InsertRsIdAsync(addentity);
            // //新增添加的用户角色
            var adds = new List<SysUserRole>();
            foreach (var roleid in input.RoleIds) adds.Add(new SysUserRole { RoleId = roleid, UserId = userid });
            await db.InsertRsIdAsync(adds);

            #endregion 新增

            return userid;
        }
    }


    /// <summary>
    ///     修改用户角色
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [OperationId(nameof(UpdateUserRole))]
    [PgApiAction("修改用户角色", Action = "UpdateUserRole", Sort = 3)]
    public async Task<bool> UpdateUserRole(ApiUserRoleInput input)
    {
        if (input.UserId == 0) throw Oops.Oh("用户选择错误");
        //找到这个用户有哪些角色
        var dbUserRoleIds = db.Queryable<SysUserRole>().Where(w => w.UserId == input.UserId)
            .Select(w => w.RoleId)
            .ToList();

        var deleteUserRoleIds = dbUserRoleIds.Except(input.RoleIds).ToList();
        var insertUserRoles = input.RoleIds.Except(dbUserRoleIds)
            .Select(it => new SysUserRole { RoleId = it, UserId = input.UserId }).ToList();

        if (deleteUserRoleIds.Count > 0)
            await db.Deleteable<SysUserRole>().Where(w => w.UserId == input.UserId &&
                                                          deleteUserRoleIds.Contains(w.RoleId))
                .ExecuteCommandAsync();

        if (insertUserRoles.Count > 0) await db.Insertable(insertUserRoles).ExecuteCommandAsync();
        return true;
    }

    /// <summary>
    ///     删除用户
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    [OperationId(nameof(BatchDelete))]
    [PgApiAction("删除用户", Action = "BatchDelete", Sort = 4)]
    public async Task<bool> BatchDelete(List<long> ids)
    {
        var res = await db.FakeDeleteAsync<SysUser>(w => w.UserType != UserType.超级管理员 && ids.Contains(w.Id));
        return res;
    }

    /// <summary>
    ///     设置状态
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [OperationId(nameof(SetState))]
    [PgApiAction("设置状态", Action = "SetState", Sort = 5)]
    public async Task<bool> SetState(ApiStateInput input)
    {
        var result = await db.SetStateByIdAsync<SysUser>(input.Id, input.State, input.Field);


        return result;
    }
}